package util;

import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author yexi
 */
public class HttpUtils {

    /**
     * @param url        不带请求参数的 Url
     * @param fromParams 表单参数
     */
    public static String doGet(String url, Map<String, String> fromParams) {
        if (fromParams == null) {
            fromParams = new HashMap<>();
        }
        String resultString = "";
        url = getTrueUrl(url, fromParams);
        // CloseableHttpClient：建立一个可以关闭的httpClient实体。
        try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
            HttpGet httpGet = new HttpGet(url);
            httpGet.setConfig(getConfig());
            resultString = executeHttp(httpClient, httpGet);
            httpGet.releaseConnection();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return resultString;
    }

    /**
     * post请求-表单版本:也就是Content-Type设置为 application/x-www-form-urlencoded;
     */
    public static String doPostFormVer(String url, Map<String, String> fromParams) {
        if (fromParams == null) {
            fromParams = new HashMap<>();
        }
        String resultString = "";
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(url);
            httpPost.setConfig(getConfig());
            // 创建参数列表(模拟表单)
            List<NameValuePair> paramList = new ArrayList<>();
            for (Map.Entry<String, String> entry : fromParams.entrySet()) {
                paramList.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
            // 对参数进行 Url 编码
            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList, StandardCharsets.UTF_8);
            httpPost.setEntity(entity);
            resultString = executeHttp(httpClient, httpPost);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return resultString;
    }

    public static String doPostJsonVer(String url, String jsonParam) {
        return doPostJsonVer(url, jsonParam, Collections.emptyMap());
    }

    /**
     * 以 application/json; charset=utf-8 形式发送 post 请求
     *
     * @param url         url
     * @param jsonParam   请求体内的json数据
     * @param extendParam 若存在额外的请求参数——?后面的键值对
     */
    public static String doPostJsonVer(String url, String jsonParam, Map<String, String> extendParam) {
        String resultString = "";
        if (jsonParam == null) {
            jsonParam = "{}";
        }
        url = getTrueUrl(url, extendParam);
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(url);
            httpPost.setConfig(getConfig());
            // 设置发送的数据
            StringEntity stringEntity = new StringEntity(jsonParam, ContentType.APPLICATION_JSON);
            httpPost.setEntity(stringEntity);
            resultString = executeHttp(httpClient, httpPost);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return resultString;
    }

    private static RequestConfig getConfig() {
        // 设置请求超时时间
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000).setConnectTimeout(60000).setConnectionRequestTimeout(60000).build();
        return requestConfig;
    }

    private static String executeHttp(CloseableHttpClient httpClient, HttpRequestBase request) throws IOException {
        // 执行http请求，获取响应对象
        try (CloseableHttpResponse response = httpClient.execute(request)) {
            System.out.println("请求结果: " + (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK));
            HttpEntity httpEntity = response.getEntity();
            //读取响应的实体内容并将其作为字符串返回。使用来自实体的字符集（如果有）转换内容，否则使用"ISO-8859-1"。
            return EntityUtils.toString(httpEntity);
        } finally {
            request.releaseConnection();
        }
    }

    private static String getTrueUrl(String url, Map<String, String> fromParams) {
        if (!fromParams.isEmpty()) {
            url += fromParams.entrySet().stream().map(e -> {
                try {
                    return e.getKey() + "=" + URLEncoder.encode(e.getValue(), "UTF-8");
                } catch (UnsupportedEncodingException ex) {
                    throw new RuntimeException(ex);
                }
            }).collect(Collectors.joining("&", "?", ""));
        }
        return url;
    }


}
